home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 076-100 / disk_093 / dme / text2.c < prev   
C/C++ Source or Header  |  1992-05-06  |  20KB  |  986 lines

  1.  
  2. /*
  3.  * TEXT2.C
  4.  *
  5.  *    (C)Copyright 1987 by Matthew Dillon, All Rights Reserved
  6.  */
  7.  
  8. #include "defs.h"
  9.  
  10. #define TU        titleupdate = 1
  11. #define nomemory()  {memoryfail = 1; TU;}
  12.  
  13. do_remeol()
  14. {
  15.     Current[Clen = E.Column] = 0;
  16.     text_sync();
  17.     text_redisplaycurrline();
  18. }
  19.  
  20. do_wleft()
  21. {
  22.     register u_char *ptr;
  23.     register int i;
  24.  
  25.     for (;;) {
  26.     i = E.Column;
  27.     if (i == 0)
  28.         goto prevline;
  29.     --i;
  30.     while (i && Current[i] == ' ')
  31.         --i;
  32.     if (i == 0 && Current[0] == ' ') {
  33. prevline:
  34.         if (ComLineMode || E.Line == 0) {
  35.         i = E.Column;
  36.         break;
  37.         }
  38.         text_sync();
  39.         --E.Line;
  40.         text_load();
  41.         E.Column = Clen;
  42.         continue;
  43.     }
  44.     while (i && Current[i] != ' ')
  45.         --i;
  46.     if (Current[i] == ' ')
  47.         ++i;
  48.     break;
  49.     }
  50.     E.Column = i;
  51.     text_sync();
  52. }
  53.  
  54.  
  55. do_wright()
  56. {
  57.     register u_char *ptr;
  58.     register int i;
  59.  
  60.     for (;;) {
  61.     i = E.Column;
  62.     if (i == Clen)
  63.         goto nextline;
  64.     while (i != Clen && Current[i] != ' ')  /* skip past current word */
  65.         ++i;
  66.     while (i != Clen && Current[i] == ' ')  /* to beg. of next word   */
  67.         ++i;
  68.     if (i == Clen) {
  69. nextline:
  70.         if (ComLineMode || E.Line == E.Lines - 1) {
  71.         i = E.Column;
  72.         break;
  73.         }
  74.         text_sync();
  75.         ++E.Line;
  76.         text_load();
  77.         E.Column = i = 0;
  78.         if (Current[0] != ' ')
  79.         break;
  80.         continue;
  81.     }
  82.     break;
  83.     }
  84.     E.Column = i;
  85.     text_sync();
  86. }
  87.  
  88.  
  89. do_split()        /* split line in two at cursor pos */
  90. {
  91.     u_char buf[256];
  92.  
  93.     strcpy(buf, Current+E.Column);
  94.     Current[Clen = E.Column] = '\0';
  95.     text_sync();
  96.     SetAPen(Rp, 0);
  97.     if (Nsu == 0)
  98.     RectFill(Rp, COL(0), ROW(E.Line-E.Topline), Xbase+Xpixs, ROW(E.Line-E.Topline+1)-1);
  99.     SetAPen(Rp, 1);
  100.     text_displayseg(E.Line - E.Topline, 1);
  101.     do_downadd();
  102.     do_insline();
  103.     strcpy(Current, buf);
  104.     Clen = strlen(Current);
  105.     text_sync();
  106.     text_displayseg(E.Line - E.Topline, 1);
  107.     do_up();
  108. }
  109.  
  110. do_join()
  111. {
  112.     register int i = Clen, j;
  113.  
  114.     if (E.Line + 1 < E.Lines && strlen(E.List[E.Line+1])+i <= 253) {
  115.     if (i && Current[i-1] != ' ')
  116.         Current[i++] = ' ';
  117.     strcpy(Current+i, E.List[E.Line+1]);
  118.     for (j = i; Current[j] == ' '; ++j);
  119.     for (; i >= 0 && Current[i] == ' '; --i);
  120.     if (j > i+2)
  121.         bmov(Current+j, Current+i+2, strlen(Current+j)+1);
  122.     Clen = strlen(Current);
  123.     text_sync();
  124.     text_displayseg(E.Line - E.Topline, 1);
  125.     do_down();
  126.     do_deline();
  127.     do_up();
  128.     return(1);
  129.     }
  130.     return(0);
  131. }
  132.  
  133. do_margin()
  134. {
  135.     E.Margin = atoi(av[1]);
  136. }
  137.  
  138. do_wordwrap()
  139. {
  140.     if (av[1][1] == 'n')
  141.     E.Wordwrap = 1;
  142.     if (av[1][1] == 'f')
  143.     E.Wordwrap = 0;
  144.     if (av[1][0] == 't')
  145.     E.Wordwrap = 1 - E.Wordwrap;
  146.     if (E.Wordwrap)
  147.     title("Wordwrap ON");
  148.     else
  149.     title("Wordwrap OFF");
  150. }
  151.  
  152. /*
  153.  * n == -1  :    force reformat entire paragraph
  154.  * n ==  0  :    only until line equalizes (from text_write())
  155.  *
  156.  * What is a paragraph?   A paragraph ends whenever the left justification
  157.  * gets larger, or on a blank line.
  158.  */
  159.  
  160. do_reformat(n)
  161. {
  162.     register char *str;
  163.     int nlok, lnsc, fnst, fnsc;
  164.     int column = E.Column;
  165.     int srow   = E.Line;
  166.     int crow   = srow;
  167.     int erow   = srow;
  168.     short dins = 0;        /* relative insert lines/delete lines   */
  169.     char moded = 0;        /* any modifications done at all?        */
  170.     char checked = 0;        /* for cursor positioning.            */
  171.  
  172.     if (E.Margin == 0)
  173.     E.Margin = 75;
  174.  
  175.     ++Nsu;
  176.     for (;;) {
  177.     str = (char *)E.List[E.Line+1];
  178.     fnst = 0;
  179.     fnsc = firstns(Current);
  180.     nlok = (E.Line + 1 < E.Lines && fnsc >= (fnst=firstns(str)));
  181.     if (nlok && str[0] == 0)
  182.         nlok = 0;
  183.     lnsc = lastns(Current);
  184.     if (lnsc < E.Margin) {      /* space at end of line for marg-lnsc-2 letter word    */
  185.         if (nlok == 0)      /* but no more data to joinup   */
  186.         break;          /* done */
  187.         if (E.Margin - lnsc - 2 >= wordlen(str+fnst)) {
  188.         E.Column = 0;
  189.         Clen = lastns(Current);
  190.         if (Current[Clen])
  191.             ++Clen;
  192.         moded = 1;
  193.         --dins;
  194.         if (do_join())
  195.             continue;
  196.         ++dins;
  197.         title("Error, Margin > 124");
  198.         break;
  199.         }
  200.         if (n == 0)        /* if couldn't mod line, and text_write, don't update any more */
  201.         break;
  202.         do_down();
  203.         erow = E.Line;
  204.         continue;
  205.     }
  206.                 /* no space, need to split    */
  207.                 /* find start of prev word    */
  208.     for (;;) {
  209.         register int i = lnsc;
  210.         while (i && Current[i] != ' ')
  211.         --i;
  212.         lnsc = i;
  213.         if (i >= E.Margin) {
  214.         while (i && Current[i] == ' ')
  215.             --i;
  216.         if (i < E.Margin)
  217.             break;
  218.         lnsc = i;
  219.         continue;
  220.         }
  221.         break;
  222.     }
  223.     if (lnsc) {        /* ok to split at word        */
  224.         ++lnsc;
  225.         ++dins;
  226.         E.Column = lnsc;
  227.         do_split(); /* Split at point LNSC        */
  228.         do_down();        /* must insert proper amount?    */
  229.         {
  230.         int indent = (nlok == 0) ? fnsc : fnst;
  231.         if (!checked) {
  232.             checked = 1;
  233.             if (lnsc <= column) {   /* if split before cursor    */
  234.             column = column - E.Column + indent;
  235.             ++crow;
  236.             }
  237.         }
  238.         if (Clen + indent < 253) {
  239.             bmov(Current, Current + indent, strlen(Current)+1);
  240.             bset(Current, indent, ' ');
  241.             Clen += indent;
  242.         }
  243.         }
  244.         erow = E.Line;
  245.         continue;
  246.     }
  247.     if (n == 0)
  248.         break;
  249.     do_down();
  250.     }
  251.     if (column < 0 || column > 200) {
  252.     printf ("Col failure: %ld\n", column);
  253.     column = 0;
  254.     }
  255.     if (srow >= E.Lines) {
  256.     srow = E.Lines - 1;
  257.     goto ra;
  258.     }
  259.     if (dins || srow < E.Topline || srow >= E.Topline + Rows) {
  260. ra:
  261.     text_sync();
  262.     --Nsu;
  263.     E.Line = crow;
  264.     E.Column = column;
  265.     text_load();
  266.     if (!text_sync())
  267.         text_redisplay();
  268.     } else {
  269.     text_sync();
  270.     --Nsu;
  271.     E.Line = crow;
  272.     E.Column = column;
  273.     text_load();
  274.     if (erow != srow) {
  275.         if (!text_sync()) {
  276.         ++erow;
  277.         if (erow - E.Topline > Rows)
  278.             erow = E.Topline + Rows;
  279.         SetAPen(Rp, 0);
  280.         RectFill(Rp, COL(0), ROW(srow - E.Topline), Xbase+Xpixs, ROW(erow - E.Topline)-1);
  281.         SetAPen(Rp, 1);
  282.         text_displayseg(srow - E.Topline, erow - srow);
  283.         }
  284.     } else {
  285.         text_sync();
  286.         if (moded)
  287.         text_redisplaycurrline();
  288.     }
  289.     }
  290.     if (column > Clen) {
  291.     bset(Current+Clen, column - Clen, ' ');
  292.     Current[column] = 0;
  293.     }
  294.     E.Column = column;
  295. }
  296.  
  297.  
  298. do_tabstop()
  299. {
  300.     E.Tabstop = atoi(av[1]);
  301. }
  302.  
  303.  
  304. do_insertmode()
  305. {
  306.     if (av[1][0]) {
  307.     switch(av[1][1] & 0x1F) {
  308.     case 'n'&0x1F:
  309.         E.Insertmode = 1;
  310.         break;
  311.     case 'f'&0x1F:
  312.         E.Insertmode = 0;
  313.         break;
  314.     case 'o'&0x1F:
  315.         E.Insertmode = 1 - E.Insertmode;
  316.         break;
  317.     }
  318.     if (E.Insertmode)
  319.         title("Insert mode on");
  320.     else
  321.         title("Insert mode off");
  322.     }
  323. }
  324.  
  325. do_insline()
  326. {
  327.     register u_char *ptr;
  328.  
  329.     TU;
  330.     E.Modified = 1;
  331.     text_sync();
  332.     if (makeroom(32) && (ptr = MAllocate(1))) {
  333.     bmov(E.List+E.Line, E.List+E.Line+1, sizeof(char *) * (E.Lines-E.Line));
  334.     E.List[E.Line] = ptr;
  335.     *ptr = 0;
  336.     ++E.Lines;
  337.     if (E.Line < E.BSline)
  338.         ++E.BSline;
  339.     if (E.Line <= E.BEline)
  340.         ++E.BEline;
  341.     } else {
  342.     nomemory();
  343.     }
  344.     text_load();
  345.     if (Nsu == 0)
  346.     ScrollRaster(Rp,0,-Ysize, COL(0), ROW(E.Line-E.Topline), COL(Columns)-1, ROW(Rows)-1);
  347.     text_displayseg(E.Line - E.Topline, 1);
  348. }
  349.  
  350. do_deline()
  351. {
  352.     int delline;
  353.  
  354.     if (E.Lines > 1) {
  355.     TU;
  356.     E.Modified = 1;
  357.     text_sync();
  358.     FreeMem(E.List[E.Line], strlen(E.List[E.Line])+1);
  359.     bmov(E.List+E.Line+1, E.List+E.Line, sizeof(char *) * (E.Lines-E.Line-1));
  360.     if (E.Line < E.BSline)
  361.         --E.BSline;
  362.     if (E.Line <= E.BEline)
  363.         --E.BEline;
  364.     delline = E.Line;
  365.     if (E.Line >= --E.Lines) {
  366.         --E.Line;
  367.         text_load();
  368.         if (E.Line < E.Topline) {
  369.         if (Nsu == 0) {
  370.             E.Topline = E.Line - (Rows>>1);
  371.             if (E.Topline < 0)
  372.             E.Topline = 0;
  373.             text_redisplay();
  374.         }
  375.         return(0);
  376.         }
  377.     }
  378.     text_load();
  379.     if (Nsu == 0)
  380.         ScrollRaster(Rp,0,Ysize, COL(0), ROW(delline-E.Topline), COL(Columns)-1, ROW(Rows)-1);
  381.     text_displayseg(Rows-1, 1);
  382.     } else {
  383.     do_firstcolumn();
  384.     do_remeol();
  385.     E.Modified = 0;
  386.     }
  387. }
  388.  
  389. do_edit()
  390. {
  391.     long fi;
  392.     long oldlock;
  393.     long lines;
  394.     u_char buf[256];
  395.     u_char ebuf[256];
  396.     u_char *ptr;
  397.     char failed = 1;
  398.     short iwiny;
  399.  
  400.     TU;
  401.     text_sync();
  402.     if (*av[0] == 'n') {        /* newfile or insfile   */
  403.     if (E.Modified && getyn("Delete modified Image?") == 0)
  404.         return(0);
  405.     iwiny = E.IWiny;
  406.     text_uninit();
  407.     text_init();
  408.     E.IWiny = iwiny;
  409.     E.Modified = 0;
  410.     E.Line = E.Topline = 0;
  411.     strncpy(E.Name, av[1], 63);
  412.     } else {
  413.     E.Modified = 1;
  414.     }
  415.     lines = E.Lines;
  416.     if (Wbs && Wdisable == 0)
  417.     oldlock = CurrentDir(E.dirlock);
  418.     if (fi = xopen(av[1], "r", 4096)) {
  419.     register int i, j;
  420.     char oktitle = 1;
  421.  
  422.     title("Loading...");
  423.     while (xgets(fi, buf, 255)) {
  424.         failed = 0;
  425.         for(i = j = 0; buf[i] && j < 254; ++i) {
  426.         if (buf[i] == 9) {            /* expand tabs (always 8)    */
  427.             do {
  428.             ebuf[j++] = ' ';
  429.             } while ((j % 8) && j < 254);
  430.         } else {
  431.             ebuf[j++] = buf[i];
  432.         }
  433.         }
  434.         while (j && ebuf[j-1] == ' ')
  435.         --j;
  436.         ebuf[j] = 0;
  437.         if (makeroom(256) && (ptr = MAllocate(j+1))) {
  438.         E.List[E.Lines++] = ptr;
  439.         bmov(ebuf, ptr, j+1);
  440.         } else {
  441.         nomemory();
  442.         oktitle = 0;
  443.         break;
  444.         }
  445.     }
  446.     if (oktitle)
  447.         title("OK");
  448.     } else {
  449.     title("File Not Found");
  450.     }
  451.     xclose(fi);
  452.     if (Wbs && Wdisable == 0)
  453.     CurrentDir(oldlock);
  454.     if (E.Lines != 1 && lines == 1 && E.List[0][0] == 0) {
  455.     E.Modified = 0;
  456.     E.Line = 0;
  457.     FreeMem(E.List[0], strlen(E.List[0])+1);
  458.     bmov(E.List+1, E.List, sizeof(char *) * (--E.Lines));
  459.     } else {
  460.     if (!failed && lines <= E.Lines - 1) {
  461.         E.BSline = lines;
  462.         E.BEline = E.Lines-1;
  463.         do_bmove();
  464.     }
  465.     }
  466.     text_load();
  467.     text_redisplay();
  468. }
  469.  
  470. static char blockmode;
  471.  
  472. do_bsave()
  473. {
  474.     blockmode = 1;
  475.     do_saveas();
  476. }
  477.  
  478. do_save()
  479. {
  480.     av[1] = E.Name;
  481.     do_saveas();
  482. }
  483.  
  484. do_savetabs()
  485. {
  486.     Savetabs = (av[1][0] && av[1][1] == 'n') ? 1 : 0;
  487. }
  488.  
  489. do_saveas()
  490. {
  491.     long fi;
  492.     long oldlock;
  493.     register long i;
  494.     register short j, k;
  495.     register u_char *ptr, *bp;
  496.     long xs, xe;
  497.     u_char buf[256];
  498.     char bm;
  499.  
  500.     bm = blockmode;
  501.     if (blockmode && blockok()) {
  502.     xs = E.BSline;
  503.     xe = E.BEline + 1;
  504.     } else {
  505.     xs = 0;
  506.     xe = E.Lines;
  507.     }
  508.     blockmode = 0;
  509.     text_sync();
  510.     if (Wbs && Wdisable == 0) {     /* Write out .info file */
  511.     DISKOBJ sdo, *d;
  512.     bzero(&sdo, sizeof(sdo));
  513.     oldlock = CurrentDir(E.dirlock);
  514.     if ((d = GetDiskObject(av[1])) == NULL) {
  515.         if (getpath(Wbs->sm_ArgList[0].wa_Name, buf)) {
  516.         sdo.do_Magic = WB_DISKMAGIC;
  517.         sdo.do_Version = WB_DISKVERSION;
  518.         makemygadget(&sdo.do_Gadget);
  519.         sdo.do_Type = WBPROJECT;
  520.         sdo.do_DefaultTool = buf;
  521.         sdo.do_ToolTypes = NULL;
  522.         sdo.do_CurrentX = NO_ICON_POSITION;
  523.         sdo.do_CurrentY = NO_ICON_POSITION;
  524.         sdo.do_DrawerData = NULL;
  525.         sdo.do_ToolWindow = NULL;
  526.         sdo.do_StackSize = 8192;
  527.         PutDiskObject(av[1], &sdo);
  528.         }
  529.     } else {
  530.         FreeDiskObject(d);
  531.     }
  532.     }
  533.     if (fi = xopen(av[1], "w", 4096)) {
  534.     xasync(fi, 1);
  535.     title("Saving...");
  536.     for (i = xs; i < xe; ++i) {
  537.         ptr = E.List[i];
  538.         if (Savetabs) {
  539.         for (bp = buf, j = 0; *ptr; ++ptr, ++bp, j = (j+1)&7) {
  540.             *bp = *ptr;
  541.             if (j == 7 && *bp == ' ' && *(bp-1) == ' ') {
  542.             k = j;
  543.             while (k-- >= 0 && *bp == ' ')
  544.                 --bp;
  545.             *++bp = 9;
  546.             } else {
  547.             if (*bp == '\"' || *bp == '\'' || *bp == '\`')
  548.                 break;
  549.             }
  550.         }
  551.         strcpy(bp, ptr);
  552.         ptr = buf;
  553.         }
  554.         if (xwrite(fi, ptr, strlen(ptr)) == 0 || xwrite(fi, "\n", 1) == 0) {
  555.         xclose(fi);
  556.         goto err;
  557.         }
  558.     }
  559.     if (xclose(fi) == 0) {
  560. err:        Abortcommand = 1;
  561.         title("WRITE FAILED!");
  562.     } else {
  563.         E.Modified &= bm;
  564.         title("OK");
  565.     }
  566.     if (Wbs && Wdisable == 0)
  567.         CurrentDir(oldlock);
  568.     } else {
  569.     title("Unable to open write file");
  570.     Abortcommand = 1;
  571.     }
  572. }
  573.  
  574.  
  575. do_block()        /* block, unblock    */
  576. {
  577.     switch(av[0][0]) {
  578.     case 'b':
  579.     if (E.BSline < 0) {
  580.         E.BSline = E.Line;
  581.         title("Block Begin");
  582.     } else {
  583.         if (E.BEline >= 0) {
  584.         title("Block Already Marked");
  585.         break;
  586.         }
  587.         title("Block End");
  588.         E.BEline = E.Line;
  589.         if (E.BSline > E.BEline) {
  590.         E.BEline = E.BSline;
  591.         E.BSline = E.Line;
  592.         }
  593.     }
  594.     break;
  595.     case 'u':
  596.     E.BSline = E.BEline = -1;
  597.     title ("Block Unmarked");
  598.     break;
  599.     }
  600. }
  601.  
  602. static
  603. blockok()
  604. {
  605.     if (E.BSline >= 0 && E.BEline >= 0 && E.BSline <= E.BEline && E.BEline < E.Lines)
  606.     return(1);
  607.     E.BSline = E.BEline = -1;
  608.     title("Block Not Specified");
  609.     return(0);
  610. }
  611.  
  612.  
  613. do_bdelete()
  614. {
  615.     register long i, n;
  616.  
  617.     if (blockok()) {
  618.     text_sync();
  619.     n = E.BEline - E.BSline + 1;
  620.     if (E.Line >= E.BSline && E.Line <= E.BEline)
  621.         E.Line = E.BSline;
  622.     if (E.Line > E.BEline)
  623.         E.Line -= n;
  624.     for (i = E.BSline; i < E.BEline; ++i)
  625.         FreeMem(E.List[i], strlen(E.List[i])+1);
  626.     bmov(E.List+E.BEline+1,E.List+E.BSline,(E.Lines-E.BEline-1)*sizeof(E.List[0]));
  627.     E.Lines -= n;
  628.     E.Modified = 1;
  629.     if (E.Line >= E.Lines)
  630.         E.Line = E.Lines - 1;
  631.     if (E.Line < 0)
  632.         E.Line = 0;
  633.     if (E.Lines == 0) {
  634.         text_uninit();
  635.         text_init();
  636.     }
  637.     TU;
  638.     text_load();
  639.     E.BSline = E.BEline = -1;
  640.     if (!text_sync())
  641.         text_redisplay();
  642.     }
  643. }
  644.  
  645.  
  646. do_bcopy()
  647. {
  648.     register u_char **list;
  649.     register long lines, i;
  650.     register ED *e;
  651.  
  652.     if (blockok()) {
  653.     text_sync();
  654.     lines = E.BEline - E.BSline + 1;
  655.     list = (u_char **)MAllocate(sizeof(char *) * (E.Lines+lines));
  656.     if (list) {
  657.         for (i = 0; i < lines; ++i) {
  658.         list[E.Line + i] = MAllocate(strlen(E.List[E.BSline+i])+1);
  659.         strcpy(list[E.Line + i], E.List[E.BSline+i]);
  660.         }
  661.         bmov(E.List+0, list, E.Line * sizeof(char *));
  662.         bmov(E.List+E.Line, list + E.Line + lines, (E.Lines-E.Line)*sizeof(char *));
  663.     }
  664.     FreeMem(E.List, E.Maxlines * 4);
  665.     E.List = list;
  666.     E.Lines += lines;
  667.     E.Maxlines = E.Lines;
  668.     text_load();
  669.     E.BSline = E.BEline = -1;
  670.     if (!text_sync())
  671.         text_redisplay();
  672.     }
  673. }
  674.  
  675.  
  676. do_bmove()
  677. {
  678.     register long lines;
  679.     register u_char **temp;
  680.  
  681.     if (blockok()) {
  682.     if (E.Line >= E.BSline && E.Line <= E.BEline) {
  683.         title("Cannot Move into self");
  684.         return(0);
  685.     }
  686.     text_sync();
  687.     lines = E.BEline - E.BSline + 1;
  688.     temp = (u_char **)MAllocate(lines * sizeof(char *));
  689.     bmov(E.List + E.BSline, temp, lines * sizeof(char *));
  690.     if (E.Line > E.BSline) {
  691.         bmov(E.List+E.BEline+1, E.List+E.BSline, (E.Line-E.BEline-1)*4);
  692.         bmov(temp, E.List + E.Line - lines, lines * 4);
  693.     } else {
  694.         bmov(E.List+E.Line, E.List+E.Line+lines, (E.BSline-E.Line)*4);
  695.         bmov(temp, E.List + E.Line, lines * 4);
  696.     }
  697.     FreeMem(temp, lines * sizeof(char *));
  698.     E.BSline = E.BEline = -1;
  699.     text_load();
  700.     if (!text_sync())
  701.         text_redisplay();
  702.     }
  703. }
  704.  
  705.  
  706. /*
  707.  * IF condition trueaction, IFELSE condition trueaction falseaction
  708.  *
  709.  *  condition:    !condition NOT the specified condition.
  710.  *        #       toggle number is SET
  711.  *        top       top of file (on first line)
  712.  *        bot       end of file (on last line)
  713.  *        left       start of line (leftmost column)
  714.  *        right       end of line (nothing but spaces under and to the right)
  715.  *        modified   text has been modified
  716.  *        insert       currently in insert mode
  717.  *        y[<=>]#    cursor is (any OR combo of <,>,=) row #  (line numbers start at 1)
  718.  *        x[<=>]#    cursor is (<,>,<=,>=,<>) column #        (columns start at 1)
  719.  *                <> means 'not equal'
  720.  *
  721.  *        cl       char under cursor is lower case
  722.  *        cu       char under cursor is upper case
  723.  *        ca       char under cursor is alpha
  724.  *        cn       char under cursor is numeric
  725.  *        cb       char within selected block
  726.  *        c[<=>]#    char under cursor is (combo of <,>,and =) #
  727.  */
  728.  
  729. do_if()
  730. {
  731.     char haselse = (av[0][2] == 'e');
  732.     char iswhile = (av[0][0] == 'w');
  733.     char istrue, notop = 0;
  734.     char c, cx, cc;
  735.     u_char *buf1, *buf2;
  736.     register u_char *ptr;
  737.     int i, cxn, cn;
  738.  
  739.     buf1 = (u_char *)malloc(256);
  740.     buf2 = (u_char *)malloc(256);
  741.     if (buf1 == NULL || buf2 == NULL) {
  742.     if (buf1) free(buf1);
  743.     if (buf2) free(buf2);
  744.     title("No Memory!");
  745.     return(0);
  746.     }
  747.     breakreset();
  748.     ptr = av[1];
  749.     if (*ptr == '!') {
  750.     notop = 1;
  751.     ++ptr;
  752.     }
  753.     c = ptr[0];
  754.     cn= atoi(ptr);
  755.     cx= ptr[1];
  756.     cxn=atoi(ptr+1);
  757.     strcpy(buf1, av[2]);
  758.  
  759. loop:
  760.     istrue = 0;
  761.     i = 0;
  762.     switch(c) {
  763.     case 'x':
  764.     i = E.Column + 1;
  765.     case 'y':
  766.     if (!i)
  767.         i = E.Line + 1;
  768. conditional:
  769.     {
  770.         register int j, n;
  771.         char any = 0;
  772.  
  773.         for (j = 1; ptr[j] && (ptr[j]<'0'||ptr[j]>'9'); ++j);
  774.         n = atoi(ptr+j);
  775.         for (j = 1; ptr[j]; ++j) {
  776.         switch(ptr[j]) {
  777.         case '<':
  778.             any = 1;
  779.             if (i < n)
  780.             istrue = 1;
  781.             break;
  782.         case '=':
  783.             any = 1;
  784.             if (i == n)
  785.             istrue = 1;
  786.             break;
  787.         case '>':
  788.             any = 1;
  789.             if (i > n)
  790.             istrue = 1;
  791.             break;
  792.         }
  793.         }
  794.         if (!any && i == n)  /* default is equivalence   */
  795.         istrue = 1;
  796.     }
  797.     break;
  798.     case 't':
  799.     istrue = E.Line == 0;
  800.     break;
  801.     case 'b':
  802.     istrue = E.Line == E.Lines-1;
  803.     break;
  804.     case 'l':
  805.     istrue = E.Column == 0;
  806.     break;
  807.     case 'r':
  808.     istrue = E.Column == Clen;
  809.     break;
  810.     case 'm':
  811.     text_sync();
  812.     istrue = E.Modified != 0;
  813.     break;
  814.     case 'i':
  815.     istrue = E.Insertmode != 0;
  816.     break;
  817.     case 'c':
  818.     cc = Current[E.Column];
  819.     switch(cx) {
  820.     case 'b':
  821.         istrue = E.Line >= E.BSline && E.Line <= E.BEline;
  822.         break;
  823.     case 'l':
  824.         istrue = cc >= 'a' && cc <= 'z';
  825.         break;
  826.     case 'u':
  827.         istrue = cc >= 'A' && cc <= 'Z';
  828.         break;
  829.     case 'a':
  830.         istrue = (cc>='a'&&cc<='z')||(cc>='A'&&cc<='Z')||(cc>='0'&&cc<='9');
  831.         break;
  832.     case 'n':
  833.         istrue = (cc >= '0' && cc <= '9');
  834.         break;
  835.     default:        /* c[<=>]#  */
  836.         i = Current[E.Column];
  837.         goto conditional;
  838.         break;
  839.     }
  840.     break;
  841.     default:
  842.     if (c >= '0' && c <= '9')
  843.         istrue = do_toggle(cn) != 0;
  844.     else
  845.         title("bad conditional");
  846.     break;
  847.     }
  848.     istrue ^= notop;
  849.     if (istrue) {
  850.     strcpy(buf2, buf1);    /* could be executed multiple times */
  851.     if (do_command(buf2) == 0)
  852.         goto done;
  853.     if (iswhile) {
  854.         if (breakcheck())
  855.         Abortcommand = 1;
  856.         else
  857.         goto loop;
  858.     }
  859.     } else {
  860.     if (haselse) {        /* only executed once */
  861.         strcpy(buf2, av[3]);
  862.         do_command(buf2);
  863.     }
  864.     }
  865. done:
  866.     free(buf1);
  867.     free(buf2);
  868. }
  869.  
  870.  
  871. /*
  872.  * TOGGLE #, SETTOGGLE #, RESETTOGGLE #
  873.  */
  874.  
  875. do_toggle(n)
  876. {
  877.     static char tg[MAXTOGGLE];
  878.     int i;
  879.  
  880.     if (n >= 0) {
  881.     if (n >= MAXTOGGLE)
  882.         return(0);
  883.     return(tg[n]);
  884.     }
  885.     i = atoi(av[1]);
  886.     if (i >= 0 && i < MAXTOGGLE) {
  887.     switch(av[0][0]) {
  888.     case 't':
  889.         tg[i] = !tg[i];
  890.         break;
  891.     case 's':
  892.         tg[i] = 1;
  893.         break;
  894.     case 'r':
  895.         tg[i] = 0;
  896.         break;
  897.     }
  898.     }
  899. }
  900.  
  901.  
  902. do_tlate()
  903. {
  904.     register u_char *ptr = av[1];
  905.     register int n;
  906.     char c = Current[E.Column];
  907.  
  908.     if (ptr[0] == '+')
  909.     c += atoi(ptr+1);
  910.     else
  911.     if (ptr[0] == '-')
  912.     c -= atoi(ptr+1);
  913.     else
  914.     c = atoi(ptr);
  915.     if (c) {
  916.     if (Current[E.Column] == 0)
  917.         Current[E.Column+1] = 0;
  918.     Current[E.Column] = c;
  919.     if (Nsu == 0) {
  920.         movetocursor();
  921.         Text(Rp, Current+E.Column, 1);
  922.     }
  923.     }
  924. }
  925.  
  926. /*
  927.  *  BSOURCE
  928.  *
  929.  *  note that since the start and end lines are loaded immediately and the
  930.  *  block unblock'd before execution starts, you can theoretically have
  931.  *  another BSOURCE as part of this BSOURCE (but be carefull!).
  932.  */
  933.  
  934. do_bsource()
  935. {
  936.     u_char buf[256];
  937.     register int i, sl, se;
  938.  
  939.     if (blockok()) {
  940.     sl = E.BSline;
  941.     se = E.BEline + 1;
  942.     E.BSline = E.BEline = -1;
  943.  
  944.     for (i = sl; i < se && i < E.Lines; ++i) {
  945.         text_sync();    /* make sure we are using latest text */
  946.         strcpy(buf, E.List[i]);
  947.         if (do_command(buf) == 0)
  948.         break;
  949.     }
  950.     }
  951. }
  952.  
  953. movetocursor()
  954. {
  955.     Move(Rp, XTbase+(E.Column-E.Topcolumn)*Xsize, YTbase+(E.Line-E.Topline)*Ysize);
  956. }
  957.  
  958. u_char *
  959. MAllocate(bytes)
  960. {
  961.     return(AllocMem(bytes, MEMF_CLEAR|MEMF_PUBLIC));
  962. }
  963.  
  964.  
  965. makeroom(n)
  966. {
  967.     register u_char **Newlist;
  968.  
  969.     if (E.Lines >= E.Maxlines) {
  970.     Newlist = (u_char **)MAllocate(sizeof(char *) * (E.Maxlines + n));
  971.     if (Newlist) {
  972.         bmov(E.List, Newlist, sizeof(char *) * E.Maxlines);
  973.         FreeMem(E.List, sizeof(char *) * E.Maxlines);
  974.         E.List = Newlist;
  975.         E.Maxlines += n;
  976.         return(1);
  977.     } else {
  978.         nomemory();
  979.     }
  980.     return(0);
  981.     }
  982.     return(1);
  983. }
  984.  
  985.  
  986.